package com.css.fxfzysx.modules.vaolEngineering.utils;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

/**
 * @Description: fxfzysx
 * @Author: lhl
 * @CreateDate: 2023/3/30 16:48
 * 最小二乘法
 */
public class LeastSquareMethod {
    BigDecimal[] xData;
    BigDecimal[] yData;

    public static Map<String,BigDecimal> leastSquareMethod(BigDecimal[] xData, BigDecimal[] yData) {
        return new LeastSquareMethod(xData, yData).predict();
    }

   public static void main(String[] args) {
       BigDecimal[] xData = new BigDecimal[]{BigDecimal.valueOf(6),BigDecimal.valueOf(6),BigDecimal.valueOf(6)};
       BigDecimal[] yData = new BigDecimal[]{BigDecimal.valueOf(6),BigDecimal.valueOf(6),BigDecimal.valueOf(6)};
       Map<String,BigDecimal> map = leastSquareMethod(xData, yData);
       map.forEach((k,v)->{
           System.out.println("当x轴为"+k+"时，y轴为+"+v);
       });
   }

    public Map<String,BigDecimal> predict() {
        // 计算n
        BigDecimal n = BigDecimal.valueOf(xData.length);
        // 计算x，y，xy，x²的总和
        BigDecimal totalX = BigDecimal.ZERO;
        BigDecimal totalY = BigDecimal.ZERO;
        BigDecimal totalXY = BigDecimal.ZERO;
        BigDecimal totalX2 = BigDecimal.ZERO;
        for (int i = 0; i < xData.length; i++) {
            totalX = xData[i].add(totalX);
            totalY = yData[i].add(totalY);
            totalXY = totalXY.add(xData[i].multiply(yData[i]));
            totalX2 = totalX2.add(xData[i].multiply(xData[i]));
        }
        // 计算x和y的均值
        BigDecimal meanX = totalX.divide(n,4,BigDecimal.ROUND_HALF_UP);
        BigDecimal meanY = totalY.divide(n,4,BigDecimal.ROUND_HALF_UP);
        // 计算斜率b
        BigDecimal b = (totalXY.subtract(n.multiply(meanX).multiply(meanY))).divide
                (totalX2.subtract(n.multiply(meanX).multiply(meanX)),4,BigDecimal.ROUND_HALF_UP);
        // 计算截距a
        BigDecimal a = meanY.subtract(b.multiply(meanX));
        // 预测
        Map<String, BigDecimal> map = new HashMap<>();
        map.put("a", a);
        map.put("b", b);
        return map;
    }

    public LeastSquareMethod(BigDecimal[] xData, BigDecimal[] yData) {
        this.xData = xData;
        this.yData = yData;
    }
}
